#define ACTION_NONE 0
#define ACTION_ROAM 1
#define ACTION_ATTACK 2
#define ACTION_COMBAT 3
#define ACTION_REST 4
#define ACTION_LOOT 5
#define ACTION_LOOT_PULSE 6
#define ACTION_NPC 7
#define ACTION_DESTROY 8
#define ACTION_BUFF 9
#define ACTION_PULL 10
#define ACTION_STAND 11

#define ACTION_WAIT 90
#define ACTION_EXIT 100

objectdef BotAction inherits BotBase
{
	variable string Status = ""

	variable bool LogToFile

	variable int CurrentSpot = 1
	variable point3f CurrentLocation
	
	variable int Kills = 0
	variable int Deaths = 0

	variable int WaitUntil = ${LavishScript.RunningTime}
	variable int LastKill = ${LavishScript.RunningTime}
	variable int LastLoot = ${LavishScript.RunningTime}
	variable int LastTarget = ${LavishScript.RunningTime}
	variable int LastDeath = ${LavishScript.RunningTime}
	variable int AttackStart = ${LavishScript.RunningTime}
	variable int CorpseCampCount = 0

	variable int MaxRoam = 100
	variable int LogoutTime = 0
	variable int SwitchTime = 0
	
	member InRoamRange(string GUID)
	{
		if ${Math.Distance[${This.CurrentLocation.X},${This.CurrentLocation.Y},${Spawn[${GUID}].X},${Spawn[${GUID}].Y}]} <= ${This.MaxRoam}
		{
			return TRUE
		}
		return FALSE
	}
	 
	method Wait(int MiliSeconds)
	{
		This.WaitUntil:Set[${Math.Calc[${LavishScript.RunningTime} + ${MiliSeconds}]}]
	}
	
	member DoneWaiting()
	{
		if ${This.WaitUntil} < ${LavishScript.RunningTime}
		{
			return TRUE
		}
		return FALSE
	}
	
	method HostileDeath()
	{
		This.LastKill:Set[${LavishScript.RunningTime}]
	}
	
	member State()
	{
		if !${Me(exists)}
		{
			return ACTION_WAIT
		}
		
		if ${Avatar.ExitOnStuck} && ${Move.StuckCount} > ${Avatar.ExitOnStuck}
		{
			This.Status:Set["Stuck count exceeded"]
			return ACTION_EXIT
		}
		
		if ${Math.Calc[${LavishScript.RunningTime} - ${This.LastLoot}]} < 200
		{
			This.Status:Set["Waiting"]
			return ACTION_WAIT
		}

		if ${Me.Sitting} && !${Avatar.NeedRest}
		{
			This.Status:Set["Standing"]
			return ACTION_STAND
		}

		if !${This.DoneWaiting}
		{
			This.Status:Set["Waiting until done"]
			return ACTION_WAIT
		}

		if ${Avatar.NeedPull} 
		{
			This.Status:Set["Pulling"]
			return ACTION_PULL
		}
		
		if ${Me.Combat}
		{
			This.Status:Set["In Combat"]
			return ACTION_COMBAT
		}

		if ${Avatar.NeedRest}
		{
			This.Status:Set["Resting"]
			return ACTION_REST
		}
		 
		if ${Math.Calc[${LavishScript.RunningTime} - ${This.LastKill}]} < 2000
		{
			;wait 2 sec for the corpse to become lootable
			This.Status:Set["Waiting for corpse"]
			return ACTION_WAIT
		}
		
		if ${Avatar.Loot} && !${Loot.Done}
		{
			This.Status:Set["Looting"]
			return ACTION_LOOT_PULSE
		}
		
		if ${Avatar.Loot} && ${Scan.GotLoot}
		{
			This.Status:Set["Looting"]
			return ACTION_LOOT
		}

		if !${Me.Combat} && ${Avatar.NeedBuff}
		{
			This.Status:Set["Buffing"]
			return ACTION_BUFF
		}

		if !${Scan.FindTarget.Equal[]} && ${Math.Calc[${LavishScript.RunningTime} - ${This.LastKill}]} > 500
		{
			This.Status:Set["Attacking"]
			return ACTION_ATTACK
		}
		
		return ACTION_NONE
	}
	
	method Pulse(int Priority)
	{
		variable string ID
		This.CurrentState:Set[${This.State}]
		;This:EA["${This.State}"]
		UIElement[txtStatus@Main@Pages@EQ Wanderbot]:SetText[${This.Status}]
		switch ${This.CurrentState}
		{
			case ACTION_ATTACK
			case ACTION_COMBAT
				if (!${Target(exists)} || !${Scan.FindTarget.Equal[${Target.ID}]}) && ${Math.Calc[${LavishScript.RunningTime} - ${This.LastTarget}]} > 500
				{
					This.LastTarget:Set[${LavishScript.RunningTime}]
					This.AttackStart:Set[${LavishScript.RunningTime}]
					ID:Set[${Scan.FindTarget}]
					if !${ID.Length} == 0
					{
						Target id "${ID}"
						This:EA["Attacking: ${Spawn[${ID}].Name} (L${Spawn[${ID}].Level} ${Spawn[${ID}].Body}) "]
					}
				}
				if ${Math.Calc[${LavishScript.RunningTime} - ${This.AttackStart}]} > 60000 && ${Target(exists)} && ${Target.CurrentHPs} > 90
				{
					;This:EA["Target seems bugged, blacklisting."]
					;Environment:BlackListGUID[${Target.ID}]
					;Environment:ClearTarget
				}
				Avatar:AttackPulse
				break
			case ACTION_PULL
				Avatar:PullPulse
				break
			case ACTION_REST
				Avatar:RestPulse
				break
			case ACTION_STAND
				Avatar:Stand
				break
			case ACTION_LOOT_PULSE
				Loot:Pulse
				break
			case ACTION_LOOT
				Move.StopMovement:Set[TRUE]
				This.LastLoot:Set[${LavishScript.RunningTime}]
				Loot:LootCorpse[${Scan.FindLoot}]
				break
			case ACTION_BUFF
				Avatar:BuffPulse
				break
			case ACTION_WAIT
				break
			case ACTION_DESTROY
				Inventory:DestroyPulse
				break
			case ACTION_NONE
				break
			case ACTION_EXIT
				Event[CORE_EVENT_STOP]:Execute
				break
		}
	}

	method TargetsUpdated()
	{
		variable string ID
		variable string ListItem
		variable int TargetCount = ${Scan.TargetCount}
		variable int a = ${TargetCount}
		UIElement[lstTargets@Targets@Pages@EQ Wanderbot]:ClearItems
		
		if ${Scan.Targets.Get[${a}](exists)}
		{
			do
			{
				ID:Set[${Scan.Targets.Get[${a}].ID}]

				ListItem:Set["${Spawn[${ID}].Name} L${Spawn[${ID}].Level} ${Spawn[${ID}].Body}"]
				UIElement[lstTargets@Targets@Pages@EQ Wanderbot]:AddItem[${ListItem},${ID},"ffaf0000"]
			}
			while ${Scan.Targets.Get[${a:Dec}](exists)}
		}
	}

	method ToggleLogging()
	{
		if ${UIElement[EQ Wanderbot].FindUsableChild[chkLog,checkbox].Checked}
		{
			This.LogToFile:Set[TRUE]
		}
		else
		{
			This.LogToFile:Set[FALSE]
		}
	}
	 
	method Inject()
	{
		LavishScript:RegisterEvent[ACTIONS_LOG]

		Event[ACTIONS_LOG]:AttachAtom[${This.ObjectName}:ToggleLogging]
		Event[TARGETS_UPDATED]:AttachAtom[${This.ObjectName}:TargetsUpdated]
		Event[CORE_EVENT_PULSE]:AttachAtom[${This.ObjectName}:Pulse]
	}
	 
	method Shutdown()
	{
		Event[TARGETS_UPDATED]:DetachAtom[${This.ObjectName}:TargetsUpdated]
		Event[CORE_EVENT_PULSE]:DetachAtom[${This.ObjectName}:Pulse]
	}

}